package org.bindinghelper;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;

import org.apache.log4j.Logger;

public class BeanUtil {
	private static final Logger logger = Logger.getLogger(BeanUtil.class);

    public static void copyBeanData(Object fromObject, Object toObject) throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
    {
        copyBeanData(fromObject, toObject, fromObject.getClass());
    }

    @SuppressWarnings("unchecked")
    public static void copyBeanData(Object fromObject, Object toObject, Class<?> fromClass) throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
    {
        if(fromObject instanceof Collection)
        {
            ((Collection)toObject).addAll((Collection)fromObject);
        }
        for(PropertyDescriptor propertyDescriptor : Introspector.getBeanInfo(fromClass, Object.class).getPropertyDescriptors())
        {
            if(propertyDescriptor.getWriteMethod() != null
                    && propertyDescriptor.getReadMethod() != null)
            {
            	try
            	{
            		Method targetMethod = toObject.getClass().getMethod(propertyDescriptor.getWriteMethod().getName(),
                            propertyDescriptor.getWriteMethod().getParameterTypes());
            		targetMethod.invoke(toObject,
                            new Object[]{propertyDescriptor.getReadMethod().invoke(fromObject, new Object[]{})});
            	}
            	catch(NoSuchMethodException e)
            	{
            		logger.debug("Could not find method", e);
            	}
            }
        }
    }

    public static <T> T copyBean(Class<T> fromClass, T fromObject) throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, InstantiationException, IntrospectionException
    {
        T ret = fromClass.newInstance();
        copyBeanData(fromObject, ret, fromClass);
        return ret;
    }

    @SuppressWarnings("unchecked")
    public static <T> T copyBean(T fromObject) throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, InstantiationException, IntrospectionException
    {
        Class<T> actualClass = ((Class<T>)fromObject.getClass());
        T ret = actualClass.newInstance();
        copyBeanData(fromObject, ret, actualClass);
        return ret;
    }
}
